<template>
  <div v-loading="showLoading"
       id="slideVerify"
       class="slide-verify"
       onselectstart="return false;"
       @click.stop>
    <div class="close-box">
      <span class="el-icon-close" @click="$emit('close')"/>
    </div>
    <div class="verify-title">
      <div class="title">
        身份验证
      </div>
      <div class="desc">
        拖动滑块，使图片角度为正
      </div>
    </div>
    <div class="verify-info">
      <div :style="{
          backgroundImage: 'url(' + verifyImg + ')',
          transform: 'rotate(' + rotate +'deg)'
      }" class="verify-img"/>
    </div>
    <!--<div
      class="slide-verify-refresh-icon"
      @click="refresh" />-->

    <!-- container -->
    <div :class="{
        'container-active': containerActive,
        'container-success': containerSuccess,
        'container-fail': containerFail
      }"
         class="slide-verify-slider">
      <div :style="{width: sliderMaskWidth}"
           class="slide-verify-slider-mask">
        <!-- slider -->
        <div :style="{left: sliderLeft}"
             class="slide-verify-slider-mask-item"
             @mousedown="sliderDown"
             @touchstart="touchStartEvent"
             @touchmove="touchMoveEvent"
             @touchend="touchEndEvent">
          <div class="slide-verify-slider-mask-item-icon"/>
        </div>
      </div>
      <span class="slide-verify-slider-text">{{ sliderText }}</span>
    </div>
  </div>
</template>


<script setup>

import {verfyCodeAPI} from '/src/api/login.js'
import {onMounted, ref} from "vue";

/**
 * vue-monoplasty-slide-verify
 * @see https://github.com/monoplasty/vue-monoplasty-slide-verify
 */
defineOptions({
  name: 'SlideVerify',
})

const props = defineProps({
  phone: String,
  sliderText: {
    type: String,
    default: 'Slide filled right'
  }
})


const w = ref(300)

// 拖拽条状态
const containerActive = ref(false) // container active class
const containerSuccess = ref(false) // container success class
const containerFail = ref(false) // container fail class

const verifyImg = ref(getRandomImg())
const originX = ref(undefined)

// 鼠标按下
const isMouseDown = ref(false)

// 拖拽柄距离左的距离
const sliderLeft = ref(0) // block right offset

const rotate = ref(0)

// 标记拖拽进度的宽
const sliderMaskWidth = ref(0) // mask width

const showLoading = ref(false)

onMounted(() => {
  init()
})

function init() {
  bindEvents()
}

// 随机生成img src
function getRandomImg() {
  // return (
  //   'https://picsum.photos/300/150/?image=' +
  //   this.getRandomNumberByRange(0, 1084)
  // )
  return `/api/captcha/${getRandomNumberByRange(1, 20)}`
}

function getRandomNumberByRange(start, end) {
  return Math.round(Math.random() * (end - start) + start)
}

const emits = defineEmits(['refresh', 'success', 'fail'])

function refresh() {
  reset()
  emits('refresh')
}

function sliderDown(event) {
  originX.value = event.clientX
  isMouseDown.value = true
}

function touchStartEvent(e) {
  originX.value = e.changedTouches[0].pageX
  isMouseDown.value = true
}

function bindEvents() {
  document.addEventListener('mousemove', e => {
    if (!isMouseDown.value) return false
    const moveX = e.clientX - originX.value

    if (moveX < 0 || moveX + 38 >= w.value) return false
    sliderLeft.value = moveX + 'px'
    if (moveX > 0) {
      const rotate = parseInt((moveX / 260) * 360)
      rotate.value = rotate > 360 ? 360 : rotate
    } else {
      rotate.value = 0
    }


    containerActive.value = true // add active
    sliderMaskWidth.value = moveX + 'px'
  })
  document.addEventListener('mouseup', e => {
    if (!isMouseDown.value) return false
    isMouseDown.value = false
    if (e.clientX === originX.value) return false
    containerActive.value = false // remove active
    verify()
  })
}

function touchMoveEvent(e) {
  if (!isMouseDown.value) return false
  const moveX = e.pageX - originX.value

  if (moveX < 0 || moveX + 38 >= w.value) return false
  sliderLeft.value = moveX + 'px'
  if (moveX > 0) {
    const rotate = parseInt((moveX / 260) * 360)
    rotate.value = rotate > 360 ? 360 : rotate
  } else {
    rotate.value = 0
  }


  containerActive.value = true // add active
  sliderMaskWidth.value = moveX + 'px'
}

function touchEndEvent(e) {
  if (!isMouseDown.value) return false
  isMouseDown.value = false
  if (e.pageX === originX.value) return false
  containerActive.value = false // remove active
  verify()
}

/**
 * 验证结果
 */
function verify() {
  showLoading.value = true
  verfyCodeAPI({
    tel: props.phone,
    angle: rotate.value
  }).then(res => {
    showLoading.value = false
    if (res.data == 1) {
      containerSuccess.value = true
      emits('success')
    } else {
      containerFail.value = true
      emits('fail')
      setTimeout(() => {
        reset()
      }, 1000)
    }
  }).catch(() => {
    showLoading.value = false
    reset()
  })
}

function reset() {
  containerActive.value = false
  containerSuccess.value = false
  containerFail.value = false
  sliderLeft.value = 0
  sliderMaskWidth.value = 0
  rotate.value = 0

  // generate img
  verifyImg.value = getRandomImg()
}


</script>


<style scoped lang="scss">
.slide-verify {
  position: relative;
  background-color: white;
  width: 100%;
  padding: 15px;
}

.slide-verify-block {
  position: absolute;
  left: 0;
  top: 0;
}

.close-box {
  text-align: right;

  .el-icon-close {
    font-size: 18px;
    cursor: pointer;
  }
}

.verify-title {
  text-align: center;
  margin-top: 5px;

  .title {
    color: #666;
  }

  .desc {
    font-size: 18px;
    color: #333;
    margin-top: 5px;
  }
}

.verify-info {
  position: relative;
  overflow: hidden;
  width: 150px;
  height: 150px;
  margin: 35px auto;
  background-size: 100% 100%;
}

.verify-img {
  position: relative;
  z-index: 2;
  width: 100%;
  height: 100%;
  background-size: 100% 100%;
  background-repeat: no-repeat;
  pointer-events: none;
  border-radius: 50%;
}

.slide-verify-refresh-icon {
  position: absolute;
  right: 0;
  top: 0;
  width: 34px;
  height: 34px;
  cursor: pointer;
  background: url('/src/assets/icon_light.png') 0 -437px;
  background-size: 34px 471px;
}

.slide-verify-slider {
  position: relative;
  text-align: center;
  width: 100%;
  height: 40px;
  line-height: 40px;
  background: #f7f9fa;
  color: #45494c;
  border: 1px solid #e4e7eb;
}

.slide-verify-slider-mask {
  position: absolute;
  left: 0;
  top: 0;
  height: 40px;
  border: 0 solid #1991fa;
  background: #d1e9fe;
}

.slide-verify-slider-mask-item {
  position: absolute;
  top: 0;
  left: 0;
  width: 40px;
  height: 38px;
  background: #fff;
  box-shadow: 0 0 3px rgba(0, 0, 0, 0.1);
  cursor: pointer;
  transition: background 0.2s linear;
}

.slide-verify-slider-mask-item:hover {
  background: #1991fa;
}

.slide-verify-slider-mask-item:hover .slide-verify-slider-mask-item-icon {
  background-position: 0 -13px;
}

.slide-verify-slider-mask-item-icon {
  position: absolute;
  top: 15px;
  left: 13px;
  width: 14px;
  height: 12px;
  background: url('/src/assets/icon_light.png') 0 -26px;
  background-size: 34px 471px;
}

.container-active .slide-verify-slider-mask-item {
  height: 38px;
  top: -1px;
  border: 1px solid #1991fa;
}

.container-active .slide-verify-slider-mask {
  height: 38px;
  border-width: 1px;
}

.container-success .slide-verify-slider-mask-item {
  height: 38px;
  top: -1px;
  border: 1px solid #52ccba;
  background-color: #52ccba !important;
}

.container-success .slide-verify-slider-mask {
  height: 38px;
  border: 1px solid #52ccba;
  background-color: #d2f4ef;
}

.container-success .slide-verify-slider-mask-item-icon {
  background-position: 0 0 !important;
}

.container-fail .slide-verify-slider-mask-item {
  height: 38px;
  top: -1px;
  border: 1px solid #f57a7a;
  background-color: #f57a7a !important;
}

.container-fail .slide-verify-slider-mask {
  height: 38px;
  border: 1px solid #f57a7a;
  background-color: #fce1e1;
}

.container-fail .slide-verify-slider-mask-item-icon {
  top: 14px;
  background-position: 0 -82px !important;
}

.container-active .slide-verify-slider-text,
.container-success .slide-verify-slider-text,
.container-fail .slide-verify-slider-text {
  display: none;
}
</style>
